//
//  BlueToothService.m
//  BlueToothProject
//
//  Created by foshou on 2017/3/2.
//  Copyright © 2017年 yxw. All rights reserved.
//

#import "BlueToothService.h"
#import "BabyBluetooth.h"
#import "SelectAlert.h"
#import "SVProgressHUD.h"
#import "UIImage+Convert.h"
#import "NSData+String.h"
#import "NSString+Hex.h"
#define channelOnPeropheralView @"peripheralView"
#define BleDataLengthMax                20

//#define imageOrder1 @"2001"
//#define imageOrder2 @"2003"
//#define imageOrder3 @"2004"

// 设备特征值 -- 可做修改
static NSString *const DeviceUUID  =  @"FFF0";

@interface BlueToothService ()<CBCentralManagerDelegate,CBPeripheralDelegate>{
    CBCentralManager *theManager;
    CBPeripheral *thePerpher;
    CBCharacteristic *theSakeCC;
    NSMutableArray *_dataArr;
    SelectAlert *_selcetAleret;
//    NSData *_imageData;
    NSTimer *_overtimer;
//    NSMutableData *_mutableData;
//    NSData * imageOrderData;
}

@property (nonatomic, strong) NSMutableArray *peripherals;
@property (nonatomic, strong) NSMutableArray *peripheralsAD;
@property (nonatomic, strong) NSMutableArray *peripheralsName;

@end

@implementation BlueToothService

static BlueToothService  *sharesingleton = nil;//必须声明为一个静态方法

#pragma mark Singleton Methods
+ (instancetype)sharedDefaultManager{
    
    @synchronized(self){
        static dispatch_once_t onceToken;
        
        dispatch_once(&onceToken, ^{
            
            sharesingleton = [[self alloc] init];
            
        });
        
        return sharesingleton;
    }
}

//限制方法，类只能初始化一次
//alloc的时候调用
+ (id) allocWithZone:(struct _NSZone *)zone{
    if(sharesingleton == nil){
        sharesingleton = [super allocWithZone:zone];
    }
    return sharesingleton;
}

//拷贝方法
- (id)copyWithZone:(NSZone *)zone{
    return sharesingleton;
}

-(instancetype)init
{
    self = [super init];
    if (self) {
        self.isConnectSuccess = NO;
//        _mutableData = [[NSMutableData alloc] init];
        theManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        _peripherals = [NSMutableArray array];
        _peripheralsAD = [NSMutableArray array];
        self.peripheralsName = [NSMutableArray array];
        _dataArr = [NSMutableArray array];
    }
    return self;
}
//连接蓝牙
- (void)connectBlueTooth:(UIButton *)sender {
    //    return ;
    if (_dataArr.count > 0) {
        self.peripherals = _dataArr;
    }else{
        [SVProgressHUD showWithStatus:@"正在扫描外设"];
        if (self.changLab) {
            self.changLab(@"正在扫描外设");
        }
    }
    // 设置蓝牙扫描外设超时时间 -- 30s
    _overtimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(overTimer) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:_overtimer forMode:NSRunLoopCommonModes];
    [theManager scanForPeripheralsWithServices:nil options:nil];
}

- (void)overTimer{
    [_overtimer invalidate];
    _overtimer = nil;
    [theManager stopScan];
    [SVProgressHUD showInfoWithStatus:@"未搜索到蓝牙设备"];
    if (self.changLab) {
        self.changLab(@"未搜索到蓝牙设备");
    }
}

-(void)sendImageToBlueTooth:(UIImage *)image perHeader:(NSString *)header
{
    
    // 转换bmp
    NSData *data = [self convertBmp24:[image convertUIImageToBitmapData] headStr:header];
  
    NSLog(@"%@",[image convertUIImageToBitmapData]);

    [SVProgressHUD showWithStatus:@"正在发送中，请稍后"];
    // 异步发送数据
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //发送图片字节
        NSString *rangeStr = nil;
        NSData *subData = nil;
        for (int i = 0; i < [data length]; i += BleDataLengthMax) {
            
            //                回到主线程刷新UI
            dispatch_async(dispatch_get_main_queue(), ^{
                // 延时0.01秒 模拟蓝牙发送速度 处理传输进度计算
                float percent = i * 1.0 / data.length;
                [SVProgressHUD showProgress:percent status:[NSString stringWithFormat:@"%.0f%%",percent * 100]];
                
            });
            
            // 预加 最大包长度，如果依然小于总数据长度，可以取最大包数据大小
            if ((i + BleDataLengthMax) < [data length]) {
                rangeStr = [NSString stringWithFormat:@"%i,%i", i, BleDataLengthMax];
                subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
                [thePerpher writeValue:subData forCharacteristic:theSakeCC type:CBCharacteristicWriteWithoutResponse];
                //                //根据接收模块的处理能力做相应延时
                                usleep(20 * 1000);
            }
            else {
                rangeStr = [NSString stringWithFormat:@"%i,%i", i, (int)([data length] - i)];
                subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
                [thePerpher writeValue:subData forCharacteristic:theSakeCC type:CBCharacteristicWriteWithoutResponse];
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (self.changLab) {
                        self.changLab(@"发送成功");
                        
                    }
                    [SVProgressHUD dismiss];
                });
                
                usleep(20 * 1000);
            }
            
        }
        
    });
 
}

-(void)sendCommandToBlueTooth:(int)commandType{
    
    NSMutableData * data = [self setId:commandType];
    
    [SVProgressHUD showWithStatus:@"正在发送中，请稍后" maskType:SVProgressHUDMaskTypeGradient];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [thePerpher writeValue:data forCharacteristic:theSakeCC type:CBCharacteristicWriteWithoutResponse];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.changLab) {
                self.changLab(@"发送成功");
            }
            [SVProgressHUD showSuccessWithStatus:@"发送成功！"];
        });
    });
}

- (NSString *)convertStringToHexStr:(NSString *)str {
    if (!str || [str length] == 0) {
        return @"";
    }
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    
    NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
    
    [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        unsigned char *dataBytes = (unsigned char*)bytes;
        for (NSInteger i = 0; i < byteRange.length; i++) {
            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
            if ([hexStr length] == 2) {
                [string appendString:hexStr];
            } else {
                [string appendFormat:@"0%@", hexStr];
            }
        }
    }];
    
    return string;
}

#pragma mark - setter
- (void)setPeripherals:(NSMutableArray *)peripherals{
    _peripherals = peripherals;
    if (peripherals.count && peripherals) {
        [_selcetAleret closeAction];
        _selcetAleret =  [[SelectAlert alloc] showWithTitle:@"选择蓝牙连接" titles:self.peripheralsName selectIndex:^(NSInteger selectIndex) {
            [SVProgressHUD showWithStatus:@"开始连接设备"];
            NSLog(@"%@",self.peripheralsName[selectIndex]);
            [theManager connectPeripheral:peripherals[selectIndex] options:nil];
            [theManager stopScan];
        } selectValue:^(NSString *selectValue) {
            
        } showCloseButton:true];
        
        [_selcetAleret show];
    }
}

#pragma mark - CBCentralManagerDelegate  当前蓝牙主设备状态
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    if (central.state==CBCentralManagerStatePoweredOn) {
        [SVProgressHUD showInfoWithStatus:@"蓝牙已打开"];
    }else
    {
        switch (central.state) {
            case CBCentralManagerStateUnknown:
                NSLog(@">>>CBCentralManagerStateUnknown");
                break;
            case CBCentralManagerStateResetting:
                [SVProgressHUD showInfoWithStatus:@"蓝牙正在重置"];
                break;
            case CBCentralManagerStateUnsupported:
                [SVProgressHUD showInfoWithStatus:@"设备不支持"];
                break;
            case CBCentralManagerStateUnauthorized:
                [SVProgressHUD showInfoWithStatus:@"设备未授权状态"];
                break;
            case CBCentralManagerStatePoweredOff:
                [SVProgressHUD showInfoWithStatus:@"蓝牙已关闭，请开启蓝牙"];
                break;
            default:
                break;
        }
    }
}

//扫描到设备会进入方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    NSLog(@"扫描连接外设：%@ %@",peripheral.name,RSSI);
    [_overtimer invalidate];
    _overtimer = nil;
    NSLog(@"扫描连接外设：%@ %@",peripheral.name,RSSI);
    
    [self insertTableView:peripheral advertisementData:advertisementData];
   
}

#pragma mark 设备扫描与连接的代理
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    [SVProgressHUD showSuccessWithStatus:@"连接设备成功"];
    if (self.changLab) {
        self.changLab(@"蓝牙连接成功");
    }
    self.isConnectSuccess = YES;
    NSLog(@"连接外设成功！%@",peripheral.name);
    thePerpher = peripheral;
    [peripheral setDelegate:self];
    [peripheral discoverServices:nil];
    NSLog(@"开始扫描外设服务 %@...",peripheral.name);
    
}
//连接外设失败
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    NSLog(@"连接到外设 失败！%@ %@",[peripheral name],[error localizedDescription]);
    self.isConnectSuccess = NO;
    NSLog(@"连接到外设 失败！%@ %@",[peripheral name],[error localizedDescription]);
    NSString *infoStr = [NSString stringWithFormat:@"连接到外设 失败！%@ %@",[peripheral name],[error localizedDescription]];
    if (self.changLab) {
        self.changLab(infoStr);
    }
    [SVProgressHUD showErrorWithStatus:infoStr];
}

//扫描到服务
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    [SVProgressHUD dismiss];
    if (error){
        self.isConnectSuccess = NO;
        [SVProgressHUD showErrorWithStatus:@"扫描外设服务失败"];
        return;
    }
    NSLog(@"扫描到外设服务：%@ -> %@",peripheral.name,peripheral.services);
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
    NSLog(@"开始扫描外设服务的特征 %@...",peripheral.name);
}
//扫描到特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    if (error){
        [SVProgressHUD showInfoWithStatus:@"扫描特征失败，请重新连接"];
        self.isConnectSuccess = NO;
        return;
    }
    NSLog(@"扫描到外设服务特征有：%@->%@->%@",peripheral.name,service.UUID,service.characteristics);
    //获取Characteristic的值
    theSakeCC = service.characteristics.lastObject;
    for (CBCharacteristic *characteristic in service.characteristics){
        {                NSLog(@"-----%@",characteristic.UUID.UUIDString);
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            if ([characteristic.UUID.UUIDString isEqualToString:DeviceUUID] || [characteristic.UUID.UUIDString isEqualToString:@"FFF1"]){
                theSakeCC = characteristic;
            }
        }
    }
}
#pragma mark 设备信息处理
//扫描到具体的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
    if (error) {
        [SVProgressHUD showErrorWithStatus:@"扫描外设失败"];
        self.isConnectSuccess = NO;
        return;
    }
    NSLog(@"%@ %@",characteristic.UUID.UUIDString,characteristic.value);
}


//与外设断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    NSString *infoStr = [NSString stringWithFormat:@"与设备断开连接 %@: %@", [peripheral name], [error localizedDescription]];
    NSLog(@"%@",infoStr);
    if (self.changLab) {
        self.changLab(@"与设备断开连接");
    }
    self.isConnectSuccess = NO;
    [SVProgressHUD showInfoWithStatus:infoStr];
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    if (error) {
        NSLog(@"%s, line = %d, erro = %@",__FUNCTION__,__LINE__,error.description);
    }
}

//插入table数据
-(void)insertTableView:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData{
    if(![_dataArr containsObject:peripheral] && peripheral.name.length != 0) {
        [_dataArr addObject:peripheral];
        [_peripheralsAD addObject:advertisementData];
        [_peripheralsName addObject:peripheral.name];
    }else{
        [SVProgressHUD showErrorWithStatus:@"暂未扫描到设备！请重新扫描！"];
        if (self.changLab) {
            self.changLab(@"未搜索到设备蓝牙！");
        }
    }
    if (_dataArr.count) {
        self.peripherals = _dataArr;
    }
}

- (NSString *)converNull:(id)object{
    if ([object isKindOfClass:[NSNull class]] || object == nil) {
        return @"";
    }
    return (NSString *)object;
}
//写入出错后 会调用此方法 成功的话不调用
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    if (error) {
        if (self.changLab) {
            self.changLab(@"发送失败");
        }
        [SVProgressHUD showErrorWithStatus:@"发送失败"];
        NSLog(@"%s, line = %d, erro = %@",__FUNCTION__,__LINE__,error.description);
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    if (error) {
        NSLog(@"%s, line = %d, erro = %@",__FUNCTION__,__LINE__,error.description);
        if (self.changLab) {
            self.changLab(@"发送失败");
        }
        [SVProgressHUD showErrorWithStatus:@"发送失败"];
        return;
    }

}
#pragma mark 选择图格式并发送
-(void)transferPhotoWithImage:(UIImage *)image{
    __weak __typeof(&*self)weakSelf = self;
    SelectAlert *alert = [[SelectAlert alloc] showWithTitle:@"请选择您要发送的图片格式" titles:@[@"16*16",@"32*32"] selectIndex:^(NSInteger selectIndex) {
        if (selectIndex == 0) {
            [weakSelf sendImageToBlueTooth:[image imageByScalingAndCroppingForSize:CGSizeMake(16, 16)] perHeader:STATIC_HEAD_16];
        }else if (selectIndex == 1){
            [weakSelf sendImageToBlueTooth:[image imageByScalingAndCroppingForSize:CGSizeMake(32, 32)] perHeader:STATIC_HEAD_32];
        }
    } selectValue:^(NSString *selectValue) {
        
    } showCloseButton:YES];
    
    [alert show];
}

- (NSData*)dataWithHexstring:(NSString *)hexstring{
    NSData* aData;
    return aData = [hexstring dataUsingEncoding: NSASCIIStringEncoding];
}

-(NSData *)hexString:(NSString *)hexString {
    int j=0;
    Byte bytes[20];
    ///3ds key的Byte 数组， 128位
    for(int i=0; i<[hexString length]; i++)
    {
        int int_ch;  /// 两位16进制数转化后的10进制数
        
        unichar hex_char1 = [hexString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
        int int_ch1;
        if(hex_char1 >= '0' && hex_char1 <='9')
            int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48
        else if(hex_char1 >= 'A' && hex_char1 <='F')
            int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
        else
            int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
        i++;
        
        unichar hex_char2 = [hexString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
        int int_ch2;
        if(hex_char2 >= '0' && hex_char2 <='9')
            int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
        else if(hex_char1 >= 'A' && hex_char1 <='F')
            int_ch2 = hex_char2-55; //// A 的Ascll - 65
        else
            int_ch2 = hex_char2-87; //// a 的Ascll - 97
        
        int_ch = int_ch1+int_ch2;
        NSLog(@"int_ch=%d",int_ch);
        bytes[j] = int_ch;  ///将转化后的数放入Byte数组里
        j++;
    }
    
    NSData *newData = [[NSData alloc] initWithBytes:bytes length:[hexString length]];
    
    return newData;
}
#pragma mark - 字符串与十六进制数据转换
- (NSData *)convertHexStrToData:(NSString *)str {
    
    if (!str || [str length] == 0) {
        
        return nil;
        
    }
    
    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
    
    NSRange range;
    
    if ([str length] % 2 == 0) {
        
        range = NSMakeRange(0, 2);
        
    } else {
        
        range = NSMakeRange(0, 1);
        
    }
    
    for (NSInteger i = range.location; i < [str length]; i += 2) {
        
        unsigned int anInt;
        
        NSString *hexCharStr = [str substringWithRange:range];
        
        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
        
        [scanner scanHexInt:&anInt];
        
        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
        
        [hexData appendData:entity];
        
        range.location += range.length;
        
        range.length = 2;
        
    }
    
    NSLog(@"hexdata: %@", hexData);
    
    return hexData;
    
}

// 将bmp32位转成24位
- (NSData *)convertBmp24:(NSData*)bmp32Data headStr:(NSString *)header
{
    if(bmp32Data ==nil) {
        return nil;
    }
    
    NSString*perPixelString = [NSString string];
    
    NSData*tempData = [NSData data];
    
    NSData *data1,*data2,*data3;
    
    NSMutableData *bitmap_24bit_mdata = [NSMutableData data];
    
    const unsigned char *p = [bmp32Data bytes];
    
    int flag = 0;
    // 帧头
    NSData *perData = [NSData stringToHex:header];
    [bitmap_24bit_mdata appendData:perData];
    for(int i =0; i < [bmp32Data length]; i++) {
        
        if(flag ==3) {
            
            p++;
            
            flag =0;
            
        }else{
            
            flag++;

            perPixelString = [NSString stringWithFormat:@"%02x",*p++];
            
            tempData = [NSData stringToHex:perPixelString];
            
            if (flag == 1) {
                data1 = tempData;
            }else if (flag == 2){
                data2 = tempData;
            }else if (flag == 3){
                data3 = tempData;
                // 间隔符
                [bitmap_24bit_mdata appendData:[NSData stringToHex:@"00"]];
                // rgb
                [bitmap_24bit_mdata appendData:data3];
                [bitmap_24bit_mdata appendData:data2];
                [bitmap_24bit_mdata appendData:data1];
            }
        }
        
    }
    // 帧尾
    NSData *fixData = [NSData stringToHex:FOOT];
    [bitmap_24bit_mdata appendData:fixData];
    
    return bitmap_24bit_mdata;
}
#pragma mark int 转 data
- (NSMutableData *) setId:(int)Id {
    
    NSMutableData *mdata = [NSMutableData data];
    NSData *footData = [NSData stringToHex:FOOT];
    
    switch (Id) {
        case order1:
            [mdata appendData:[NSData stringToHex:HEAD_16_16]];
            break;
        case order2:
            [mdata appendData:[NSData stringToHex:@"01"]];
            break;
        case order3:
            [mdata appendData:[NSData stringToHex:@"02"]];
            break;
        case order4:
            [mdata appendData:[NSData stringToHex:@"03"]];
            break;
        case order5:
            [mdata appendData:[NSData stringToHex:@"04"]];
            break;
            
        default:
            break;
    }
    
    [mdata appendData:footData];
    return mdata;
}
//  普通字符串转换为十六进制的。
- (NSString *)hexStringFromString:(NSString *)string{
    NSData *myD = [string dataUsingEncoding:NSUTF8StringEncoding];
    Byte *bytes = (Byte *)[myD bytes];
    //下面是Byte 转换为16进制。
    NSString *hexStr=@"";
    for(int i=0;i<[myD length];i++)
        
    {
        NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];///16进制数
        
        if([newHexStr length]==1)
            
            hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
        
        else
            
            hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr]; 
    } 
    return hexStr; 
}


@end
